/**
 * @file CLambdaTable.hpp Deklarácia triedy CLambdaTable.
 *
 * @author Martin Kosorinský.
 * @date 1.4.2009.
 */

#ifndef CLAMBDATABLE_HEADER
#define CLAMBDATABLE_HEADER

#include "miraclExtensions.hpp"

/**
 * @brief Trieda zapúzdrujúca operácie na tabuľke, v ktorej kľúče predstavujú body
 * na eliptickej krivke typu <i>epoint*</i>, a hodnoty celé čísla typu <i>big</i>.
 * V tabuľke sú uchovávané dvojice "bod na eliptickej krivke" a "celočíselná hodnota".
 * Na uchovávanie údajov je využitý "skoro" štandardný STL kontajner @c unordered_map. Ten je
 * schopný za pomoci komparátora a hashera bodov eliptickej krivky výrazne uľahčiť
 * vyhľadávanie podľa kľúča, pre ktoré je štruktúra optimalizovaná. CLambdaTable je tak vhodné
 * využiť v prípade, keď potrebujeme čo najrýchlejšie vyhľadávať hodnoty priradené k bodom.
 * @warning Pre staršie kompilátory je štruktúra @c unordered_map nahradená štandardnou @c map.
 */
class CLambdaTable {
private:
    /**
     * @brief Kontajner, v ktorom budú uložené položky tabuľky.
     * Využíva STL kontajner @c unordered_map, ktorý pracuje na báze hashovacej tabuľky.
     */
    TLambdaEpointList table;
public:
    /**
     * @brief Iterátor pre prístup k prvkom tabuľky.
     */
    typedef TLambdaEpointList::iterator iterator;
    /**
     * @brief Konštantný iterátor prvkov tabuľky.
     */
    typedef TLambdaEpointList::const_iterator const_iterator;
    /**
     * @brief Základný konštruktor.
     * Konštruktor nealokuje žiadne prostriedky, len volá defaultné konštruktory členských premenných.
     */
    CLambdaTable();
    /**
     * @brief Kopírovací konštruktor.
     * Vytvára novú inštanciu objektu CLambdaTable ako <i>hard-copy</i> inej existujúcej inštancie CLambdaTable.
     * @param[in] tab je referencia na inštanciu CLambdaTable, ktorá slúži ako zdroj kopírovania.
     */
    CLambdaTable(const CLambdaTable &tab);
    /**
     * @brief Deštruktor.
     * Zabezpečuje korektnú dealokáciu prostriedkov. Deštruktor zabezpečí dealokáciu dynamickej pamäti, na
     * ktorú odkazujú smerníky uložené ako kľúče a hodnoty v tabuľke. Na dealokáciu kľúčov využíva procedúru
     * epoint_free() a na dealokáciu hodnôt procedúru mirkill().
     */
    ~CLambdaTable();
    /**
     * @brief Funkcia vráti počet položiek uložených v tabuľke (počet rôznych kľúčov).
     * @return Funkcia vráti počet položiek uložených v tabuľke.
     */
    inline size_t size() const {
        return table.size();
    };
    /**
     * @brief Boolovská funkcia
     * @return návratová hodnota je TRUE ak tabuľka neobsahuje žiadne položky, ináč vráti FALSE.
     */
    inline bool empty() const {
        return (table.size() == 0);
    };
    /**
     * @brief Funkcia vracia maximálny počet položiek, ktoré je možné do tabuľky umiestniť.
     * Výstup vyplýva z obmedzení použitého generického kontajneru.
     * @return Maximálny počet položiek, ktoré je možné do tabuľky umiestniť.
     */
    inline size_t max_size() const {
        return table.max_size();
    };
    /**
     * @brief Vyprázdni obsah tabuľky.
     * Všetky položky tabuľky sú odstránené vrátane korektnej dealokácie pamäti.
     */
    void clear();
    /**
     * @brief Funkcia vráti iterátor ukazujúci na prvú položku tabuľky.
     * @return Iterátor ukazujúci na prvú položku tabuľky.
     */
    inline iterator begin() {
        return table.begin();
    };
    /**
     * @brief Funkcia vráti konštantný iterátor ukazujúci na prvú položku tabuľky.
     * @return Iterátor ukazujúci na prvú položku tabuľky.
     */
    inline const_iterator begin() const {
        return table.begin();
    };
    /**
     * @brief Funkcia vráti iterátor ukazujúci za poslednú položku tabuľky.
     * @return Iterátor ukazujúci za poslednú položku tabuľky.
     */
    inline iterator end() {
        return table.end();
    };
    /**
     * @brief Funkcia vráti konštantný iterátor ukazujúci za poslednú položku tabuľky.
     * @return Iterátor ukazujúci za poslednú položku tabuľky.
     */
    inline const_iterator end() const {
        return table.end();
    };
    /**
     * @brief Vyhľadáva v tabuľke položku s kľúčom <i>P</i> a vracia iterátor ukazujúci na túto položku.
     * V prípade, že sa položka s daným kľúčom v tabuľke nenachádza, vráti iterátor ukazujúci
     * za poslednú položku tabuľky.
     * @param[in] P je kľúč, ktorý sa snažíme nájsť v tabuľke.
     * @return Konštantný iterátor ukazujúci na hľadanú položku. V prípade neúspechu hľadania
     * ukazuje za poslednú položku tabuľky.
     */
    inline const_iterator find(const epoint * P) const {
        return table.find((epoint*)P);
    };
    /**
     * @brief Rozširuje tabuľku o novú položku.
     * Tabuľka neumožňuje pridať dve rôzne položky s rovnakým kľúčom, a preto v prípade, že už
     * obsahuje položku s vkladaným kľúčom, nebude tabuľka rozšírená. Ak položku neobsahuje, do
     * tabuľky je pridaná nová.
     * Procedúra vykonáva pred uložením hard-copy kľúča aj hodnoty. To znamená, že je
     * dynamicky alokovaná pamäť, do ktorej sú skopírované vstupné dáta a do tabuľky sú
     * pridané smerníky na túto pamäť.
     * @param[in] P je bod, ktorý predstavuje kľúčovú hodnotu položky vkladanej do tabuľky.
     * @param[in] distance predstavuje hodnotu priradenú vkladanému kľúču.
     */
    void add(const epoint * P, const big distance);
    /**
     * @brief Operátor priradenia.
     * Vytvára hard-copy tabuľky na základe vstupného parametra.
     * @param[in] tab je existujúca inštancia tabuľky CLambdaTable, ktorej kópiu vytvárame.
     * @return Referenciu na novovytvorenú inštanciu CLambdaTable.
     */
    CLambdaTable& operator=(const CLambdaTable& tab);
};
#endif /* CLAMBDATABLE_HEADER */
